package com.edt.ichannel.api.service.impl;


import cc.edt.iceutils2.random.IceRandomUtils;
import cc.edt.iceutils2.string.IceStringUtils;
import cc.edt.iceutils3.json.IceFastJsonUtils;
import com.edt.ichannel.api.common.constant.CommonConstant;
import com.edt.ichannel.api.common.entity.ActionResult;
import com.edt.ichannel.api.dao.DownlinkSendDao;
import com.edt.ichannel.api.dao.DueOutDao;
import com.edt.ichannel.api.entiy.local.*;
import com.edt.ichannel.api.service.DueOutService;
import com.edt.ichannel.api.service.EdtApiService;
import com.edt.ichannel.api.service.SendNumberService;
import com.edt.ichannel.api.service.SendRuleService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 代发列表实现类
 *
 * @author 李爽
 * @date 2018/7/5 13:46
 */
@Service
public class DueOutServiceImpl implements DueOutService {
    @Resource
    private DueOutDao dueOutDao;
    @Resource
    private SendNumberService sendNumberService;
    @Resource
    private SendRuleService sendRuleService;
    @Resource(name = "redisTemplate")
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private EdtApiService edtApiService;
    @Resource
    private DownlinkSendDao downlinkSendDao;
    private Logger logger = LogManager.getLogger(DueOutServiceImpl.class);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendDueOutNumber() {
        //  已发送号码前缀
        String sendOverNumberPrefix = "OVER_SEND";
        List<SendNumber> listSendNumber = sendNumberService.getSendNumberList();
        List<DueOut> listDueOut = dueOutDao.getListDueOut();
        int sendNumberNullCount = 0;
        for (DueOut list : listDueOut) {

            String sendPhone = getSendNumber(listSendNumber);
            //如果发送号码为空则号码在下一批次发送
            if (IceStringUtils.isBlank(sendPhone)) {
                sendNumberNullCount++;
                logger.info("无匹配发送号码发送" + IceFastJsonUtils.toJsonString(list));
                continue;
            }
            ActionResult actionResult = toSendMsg(sendPhone, list);
            if (actionResult.isSuccess()) {
                logger.info("发送成功号码：" + IceFastJsonUtils.toJsonString(list));
                //存放一天内号码发送次数
                setRedis(CommonConstant.SEND_NUMBER_DAY_MAX_REDIS_PREFIX + sendPhone, 24);
                //存放一小时内号码发送次数
                setRedis(CommonConstant.SEND_NUMBER_HOUR_MAX_REDIS_PREFIX + sendPhone, 1);
                //将以发送过的记录存到redis中，防止重复发送

                DownlinkSend downlinkSend = new DownlinkSend();
                BeanUtils.copyProperties(list, downlinkSend, "id");
                downlinkSend.setId(IceRandomUtils.longUUID());
                downlinkSend.setSendDate(new Date());
                downlinkSend.setSendPhoneNumber(sendPhone);
                downlinkSend.setState("1");
                //保存号码发送下行记录
                downlinkSendDao.saveDownlinkSend(downlinkSend);
                //删除待发送记录
                dueOutDao.deleteDueOutById(list.getId());
            }


        }
//如果本批次号码 都没有匹配到号码 则删除待发送记录并保存信息
        if (sendNumberNullCount == listSendNumber.size() && listSendNumber.size() > 0) {
            for (DueOut dueOut : listDueOut) {
                DownlinkSend downlinkSend = new DownlinkSend();
                BeanUtils.copyProperties(dueOut, downlinkSend, "id");
                downlinkSend.setId(IceRandomUtils.longUUID());
                downlinkSend.setSendDate(new Date());
                downlinkSend.setState("0");
                //保存号码发送下行记录
                downlinkSendDao.saveDownlinkSend(downlinkSend);
                //删除待发送记录
                dueOutDao.deleteDueOutById(dueOut.getId());
            }
        }
    }

    /**
     * @param sendPhone sendPhone 发送号码
     * @param dueOut    dueOut 发送内容
     * @return com.edt.ichannel.api.common.entity.ActionResult
     * @author 李爽
     * @date 2018/7/11 11:28
     */
    private ActionResult toSendMsg(String sendPhone, DueOut dueOut) {
        SendSMS sendSMS = new SendSMS();
        sendSMS.setSendPhone(sendPhone);
        sendSMS.setContent(dueOut.getMessageText());
        sendSMS.setReceivePhone(dueOut.getPhoneNumber());
        return edtApiService.sendsms(sendSMS);
    }

    /**
     * 获取可发送号码(如果没有匹配返回null)
     *
     * @param listSendNumber listSendNumber
     * @return java.lang.String
     * @author 李爽
     * @date 2018/7/11 10:42
     */
    private String getSendNumber(List<SendNumber> listSendNumber) {
        SendRule sendRule = sendRuleService.getSendRule();
        for (SendNumber list : listSendNumber) {
            if (getRedisSendNumber(CommonConstant.SEND_NUMBER_HOUR_MAX_REDIS_PREFIX + list.getSendNumber()) < sendRule.getHourMaxCount()
                    && getRedisSendNumber(CommonConstant.SEND_NUMBER_DAY_MAX_REDIS_PREFIX + list.getSendNumber()) < sendRule.getDayMaxCount()) {
                return list.getSendNumber();
            }
        }
        return null;
    }

    /**
     * 获取redis中的号码一小时内 和一天发送的数量
     *
     * @param key key
     * @return int
     * @author 李爽
     * @date 2018/7/11 11:04
     */
    private int getRedisSendNumber(String key) {
        return redisTemplate.opsForValue().get(key) == null ?
                0 : Integer.parseInt(redisTemplate.opsForValue().get(key).toString());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ActionResult saveDueOut(DueOut dueOut) {
        ActionResult actionResult = new ActionResult();
        dueOut.setId(IceRandomUtils.longUUID());
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
        String messageFlow = formatter.format(new Date());
        dueOut.setMessageFlow(messageFlow);
        dueOut.setSubmissionDate(new Date());
        dueOut.setPriority("1");
        dueOutDao.saveDueOut(dueOut);
        actionResult.setSuccess(true);
        actionResult.setMessage("保存成功");
        return actionResult;
    }

    /**
     * 存放到redis中
     *
     * @param key key
     * @author 李爽
     * @date 2018/2/8 15:46
     */
    private void setRedis(String key, long time) {

        int dayCounts = redisTemplate.opsForValue().get(key) == null ? 0 : Integer.parseInt(redisTemplate.opsForValue().get(key).toString());
        if (dayCounts == 0) {
            redisTemplate.opsForValue().set(key, 1, time, TimeUnit.HOURS);
        } else {
            redisTemplate.opsForValue().increment(key, 1);
        }
    }
}
